package com.own.business.dingtalk.gov.util;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.xxpt.gateway.shared.api.request.OapiGettokenJsonRequest;
import com.alibaba.xxpt.gateway.shared.api.request.OapiRpcOauth2DingtalkAppUserJsonRequest;
import com.alibaba.xxpt.gateway.shared.client.http.ExecutableClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.own.business.dingtalk.gov.entity.po.DingTalkGovUser;
import com.own.business.dingtalk.gov.entity.vo.DingTalkGovUserVo;
import com.own.business.dingtalk.gov.mapper.DingTalkGovUserMapper;
import com.own.business.dingtalk.gov.property.DingTalkGovProperty;
import com.own.component.common.exception.BusinessException;
import com.own.component.store.core.Store;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;

/**
 * DingTalkGovUtil
 *
 * @author chenxueli
 * @date 2023-07-02 13:13:49
 */
@Slf4j
@Component
public class DingTalkGovUtil {

    private static final String DING_TALK_GOV_TOKEN_FIELD = "ding_talk_gov:token_field";
    private static ExecutableClient EXECUTABLE_CLIENT;
    @Resource
    private DingTalkGovProperty dingTalkGovProperty;
    @Resource
    private Store<String> store;

    @Resource
    private DingTalkGovUserMapper dingTalkGovUserMapper;

    private ExecutableClient getExecutableClient() {
        if (EXECUTABLE_CLIENT == null) {
            EXECUTABLE_CLIENT = ExecutableClient.getInstance();
            // DomainName不同环境对应不同域名，示例为sass域名
            EXECUTABLE_CLIENT.setDomainName(dingTalkGovProperty.getDomain());
            EXECUTABLE_CLIENT.setProtocal("https");
            // 应用App CustomEncryptKey
            EXECUTABLE_CLIENT.setAccessKey(dingTalkGovProperty.getAccessKey());
            // 应用App Secret
            EXECUTABLE_CLIENT.setSecretKey(dingTalkGovProperty.getSecretKey());
            EXECUTABLE_CLIENT.init();
            return EXECUTABLE_CLIENT;
        }
        return EXECUTABLE_CLIENT;
    }

    /**
     * 获取浙政钉的token信息
     *
     * @return token令牌信息
     */
    public String getToken() {
        var value = store.value();
        var flag = value.contains(DING_TALK_GOV_TOKEN_FIELD);
        if (flag) {
            return value.get(DING_TALK_GOV_TOKEN_FIELD);
        }
        return refreshToken();
    }

    /**
     * 刷新token信息
     *
     * @return token令牌信息
     */
    public String refreshToken() {
        // executableClient保证单例
        var client = getExecutableClient().newIntelligentGetClient("/gettoken.json");
        var request = new OapiGettokenJsonRequest();
        // 应用的唯一标识key
        request.setAppkey(dingTalkGovProperty.getAccessKey());
        // 应用的密钥
        request.setAppsecret(dingTalkGovProperty.getSecretKey());
        // 获取结果
        var apiResult = client.get(request);
        if (apiResult.getContent().getSuccess()) {
            var object = JSONObject.parseObject(apiResult.getContent().getData());
            var token = object.getString("accessToken");
            // 存入缓存，缓存有效期为7100秒
            var value = store.value();
            value.set(DING_TALK_GOV_TOKEN_FIELD, token, Duration.ofSeconds(7100));
            return token;
        }
        return null;
    }

    /**
     * 根据code获取用户信息
     *
     * @param code code
     * @return 用户信息
     */
    public DingTalkGovUserVo getDingTalkGovUserByCode(String code) {
        // executableClient保证单例
        var client = getExecutableClient().newIntelligentPostClient("/rpc/oauth2/dingtalk_app_user.json");
        var request = new OapiRpcOauth2DingtalkAppUserJsonRequest();
        // 登录access_token
        request.setAccess_token(getToken());
        // 临时授权码
        request.setAuth_code(code);
        // 获取结果
        var apiResult = client.post(request);
        if (apiResult.getSuccess()) {
            var content = JSONObject.parseObject(apiResult.getContent()).getJSONObject("content");
            log.debug("apiResult:{}", JSON.toJSONString(apiResult));
            // 转成用户对象
            var user = content.getObject("data", DingTalkGovUser.class);
            if (user == null) {
                throw new BusinessException("用户信息错误，请重新进入页面");
            }
            // 查询数据库是否已经有该数据了
            var wrapper = new QueryWrapper<DingTalkGovUser>().lambda()
                    .eq(DingTalkGovUser::getClientId, user.getClientId())
                    .eq(DingTalkGovUser::getOpenid, user.getOpenid());
            var oldUser = dingTalkGovUserMapper.selectOne(wrapper);
            if (oldUser != null) {
                // 判断是否需要修改，修改数据
                if (oldUser.getGmtModified().plusHours(1).isBefore(LocalDateTime.now())) {
                    user.setId(oldUser.getId());
                    dingTalkGovUserMapper.updateById(user);
                    return new DingTalkGovUserVo(user);
                }
                return new DingTalkGovUserVo(oldUser);
            } else {
                // 将数据存入数据库
                dingTalkGovUserMapper.insert(user);
                return new DingTalkGovUserVo(user);
            }
        }
        return null;
    }

}
